package com.dl698.buss;

import com.dl698.bean.FrameData;
import com.dl698.tools.ResultCode;
import com.dl698.util.ReverseByteArrayInputStream;
import com.dl698.util.ReverseByteArrayOutputStream;
import com.dl698.sessionlayer.hdlc.HdlcFrame;
import com.dl698.axdr.Apdu;
import com.dl698.axdr.M698pdu;
import com.dl698.parse.ParseTools;
import com.dl698.axdr.Data;
import com.dl698.parse.ParseGetResponse;
import com.dl698.parse.ParseSetResponse;
import com.dl698.parse.ParseActionResponse;
import com.dl698.parse.ParseAuthResponse;
import com.dl698.parse.ParseProxyResponse;
import com.dl698.axdr.Get_Response;
import com.dl698.axdr.Set_Response;
import com.dl698.axdr.Action_Response;
import com.dl698.axdr.Proxy_Response;
import com.dl698.axdr.Security_Response;
import com.dl698.axdr.Connect_Response;
import com.dl698.axdr.GetResponseNormal;
import com.dl698.axdr.GetResponseNormalList;
import com.dl698.axdr.ProxyGetResponseList;
import com.dl698.axdr.A_ResultNormal;
import com.dl698.axdr.A_ResultRecord;
import com.dl698.axdr.SubSeqOfProxyGetResponseResult;
import com.dl698.axdr.SubSeqOfResults;
import com.dl698.axdr.SubChoiceRespData;
import com.dl698.axdr.SubSeqOfResult;
import com.dl698.axdr.ProxyGetResponse;
import com.dl698.axdr.SubSeqOfProxyGet;
import com.dl698.axdr.ProxyGet;
import com.dl698.axdr.Get_Result;

/**
 * DL698 主业务类
 * 实现协议组帧和解帧的主要功能
 * 
 * @author wind
 * @version 1.1.1
 */
public class DL698 {

    private static DL698 instance = null;

    /**
     * 私有构造函数，实现单例模式
     */
    private DL698() {
    }

    /**
     * 获取单例实例
     * 
     * @return DL698实例
     */
    public static synchronized DL698 getInstance() {
        if (instance == null) {
            instance = new DL698();
        }
        return instance;
    }

    /**
     * 构建帧数据
     * 
     * @param param 选项参数
     * @return 构建结果
     */
    public FrameData buildFrame(Option param) {
        FrameData result = new FrameData();

        try {
            // 参数验证
            if (param == null || param.getLinkOption() == null || param.getRequestOption() == null) {
                result.setCode(ResultCode.EMPTY_ERROR);
                result.setData("link_option or request_option not allow empty");
                return result;
            }

            LinkOption linkOpt = param.getLinkOption();
            RequestOption requestOption = param.getRequestOption();

            // 链路层配置验证
            if (linkOpt.getServerAddress() == null || linkOpt.getClientAddress() == null) {
                result.setCode(ResultCode.EMPTY_ERROR);
                result.setData("server_address or client_address not allow empty");
                return result;
            }

            if (linkOpt.getServerAddress().length() != 12) {
                result.setCode(ResultCode.ILLEGAL_ERROR);
                result.setData("server_address length is Illegal");
                return result;
            }

            if (linkOpt.getClientAddress().length() != 2) {
                result.setCode(ResultCode.ILLEGAL_ERROR);
                result.setData("client_address length is Illegal");
                return result;
            }

            // 根据请求类型处理
            switch (requestOption.getRequestMode()) {
                case Choice.GET_REQUEST:
                    return handleGetRequest(requestOption, linkOpt);
                case Choice.SET_REQUEST:
                    return handleSetRequest(requestOption, linkOpt);
                case Choice.ACTION_REQUEST:
                    return handleActionRequest(requestOption, linkOpt);
                case Choice.CONNECT_REQUEST:
                    return handleConnectRequest(requestOption, linkOpt);
                case Choice.PROXY_REQUEST:
                    return handleProxyRequest(requestOption, linkOpt);
                case Choice.SECURITY_REQUEST:
                    return handleSecurityRequest(requestOption, linkOpt);
                default:
                    result.setCode(ResultCode.ILLEGAL_ERROR);
                    result.setData("request_mode is Illegal");
                    return result;
            }

        } catch (Exception e) {
            result.setCode(ResultCode.ILLEGAL_ERROR);
            result.setData("System error: " + e.getMessage());
            return result;
        }
    }

    /**
     * 解析帧数据
     * 
     * @param frameData 帧数据字节数组
     * @return 解析结果
     */
    public FrameData parseFrame(byte[] frameData) {
        FrameData result = new FrameData();

        try {
            if (frameData == null || frameData.length == 0) {
                result.setCode(ResultCode.EMPTY_ERROR);
                result.setData("frame data is empty");
                return result;
            }

            // 实现帧解析逻辑
            // 检查是否为链路层帧(以0x68开头，0x16结尾)
            if (frameData[0] == 0x68 && frameData[frameData.length - 1] == 0x16) {
                // 链路层帧解析
                result = parseLinkFrame(frameData);
            } else {
                // 应用层帧解析
                result = parseAppFrame(frameData);
            }

            return result;

        } catch (Exception e) {
            result.setCode(ResultCode.ILLEGAL_ERROR);
            result.setData("Parse error: " + e.getMessage());
            return result;
        }
    }

    /**
     * 解析链路层帧
     * 
     * @param frameData 帧数据字节数组
     * @return 解析结果
     */
    private FrameData parseLinkFrame(byte[] frameData) {
        FrameData result = new FrameData();
        try {
            // 实现链路层帧解析逻辑
            // 这里应该解析HDLC帧格式
            HdlcFrame hdlcFrame = new HdlcFrame();
            ReverseByteArrayInputStream input = new ReverseByteArrayInputStream(frameData);

            // 解码HDLC帧
            hdlcFrame.decode(input);

            // 获取信息字段并进一步解析
            byte[] infoField = hdlcFrame.getInformationField();
            if (infoField != null && infoField.length > 0) {
                // 递归解析信息字段
                FrameData appResult = parseAppFrame(infoField);
                result.setCode(appResult.getCode());
                result.setData(appResult.getData());
            } else {
                result.setCode(ResultCode.SUCCESS);
                result.setData("Link frame parsed, no information field");
            }
        } catch (Exception e) {
            result.setCode(ResultCode.ILLEGAL_ERROR);
            result.setData("Link frame parse error: " + e.getMessage());
        }
        return result;
    }

    /**
     * 解析应用层帧
     * 
     * @param frameData 帧数据字节数组
     * @return 解析结果
     */
    private FrameData parseAppFrame(byte[] frameData) {
        FrameData result = new FrameData();
        try {
            // 实现应用层帧解析逻辑
            // 按照TS698.ts的实现方式，先解析为APDU，再解析为M698pdu
            Apdu apdu = Apdu.getInstance();

            // 解码APDU (使用byte[]参数)
            apdu = apdu.decode(frameData);

            // 编码COSEM PDU到输出流
            ReverseByteArrayOutputStream output = new ReverseByteArrayOutputStream();
            output.setBufSize(3000);
            apdu.getCosemPdu().encode(output);

            // 解码M698pdu
            M698pdu m698pdu = new M698pdu();
            m698pdu.decode(new ReverseByteArrayInputStream(output.getArray()));

            // 使用parseFrame方法解析M698pdu
            String parsedData = parseFrame(m698pdu);

            result.setCode(ResultCode.SUCCESS);
            result.setData(parsedData);
        } catch (Exception e) {
            result.setCode(ResultCode.ILLEGAL_ERROR);
            result.setData("App frame parse error: " + e.getMessage());
        }
        return result;
    }

    /**
     * 解析M698pdu对象
     * 
     * @param m698pdu M698pdu对象
     * @return 解析结果字符串
     */
    private String parseFrame(M698pdu m698pdu) {
        String result = "";

        try {
            switch (m698pdu.getChoice()) {
                case GET_RESPONSE:
                    Get_Response getResponse = m698pdu.getGet_Response();
                    switch (getResponse.getChoiceIndex()) {
                        case GET_RESPONSE_NORMAL:
                            GetResponseNormal getResponseNormal = getResponse.getGetResponseNormal();
                            A_ResultNormal aResultNormal = getResponseNormal.getResult();
                            result = ParseGetResponse.parseGetResponseNormal(aResultNormal.getResult());
                            break;
                        case GET_RESPONSE_NORMAL_LIST:
                            GetResponseNormalList getResponseNormalList = getResponse.getGetResponseNormalList();
                            SubSeqOfResults subSeqOfResults = getResponseNormalList.getResults();
                            result = ParseGetResponse.parseGetResponseNormalList(subSeqOfResults);
                            break;
                        case GET_RESPONSE_RECORD:
                            A_ResultRecord aResultRecord = getResponse.getGetResponseRecord().getRespData();
                            SubChoiceRespData subChoiceRespData = aResultRecord.getResult();
                            result = ParseGetResponse.parseGetResponseRecord(subChoiceRespData);
                            break;
                        // 其他情况暂时不处理
                    }
                    break;
                case SET_RESPONSE:
                    Set_Response setResponse = m698pdu.getSet_Response();
                    switch (setResponse.getChoiceIndex()) {
                        case SET_RESPONSE_NORMAL:
                            result = ParseSetResponse.parseSetNormalResponse(setResponse.getSetResponseNormal());
                            break;
                        case SET_RESPONSE_NORMAL_LIST:
                            result = ParseSetResponse
                                    .parseSetNormalResponseList(setResponse.getSetResponseNormalList());
                            break;
                        case SET_THEN_GET_RESPONSE_NORMAL_LIST:
                            result = ParseSetResponse
                                    .parseSetThenGetResponse(setResponse.getSetThenGetResponseNormalList());
                            break;
                    }
                    break;
                case ACTION_RESPONSE:
                    Action_Response actionResponse = m698pdu.getAction_Response();
                    switch (actionResponse.getChoiceIndex()) {
                        case ACTION_RESPONSE_NORMAL:
                            result = ParseActionResponse
                                    .parseActionResponseNormal(actionResponse.getActionResponseNormal());
                            break;
                        case ACTION_RESPONSE_NORMAL_LIST:
                            result = ParseActionResponse
                                    .parseActionResponseNormalList(actionResponse.getActionResponseNormalList());
                            break;
                        case ACTION_THEN_GET_RESPONSE_NORMAL_LIST:
                            result = ParseActionResponse.parseActionThenGetResponseList(
                                    actionResponse.getActionThenGetResponseNormalList());
                            break;
                    }
                    break;
                case CONNECT_RESPONSE:
                    result = ParseAuthResponse.parseConnectResponse(m698pdu.getConnect_Response().getWConnObj());
                    break;
                case SECURITY_RESPONSE:
                    result = ParseAuthResponse.parseSecurityResponse(m698pdu.getSecurity_Response());
                    break;
                case PROXY_RESPONSE:
                    Proxy_Response proxyResponse = m698pdu.getProxy_Response();
                    switch (proxyResponse.getChoiceIndex()) {
                        case PROXY_GET_RESPONSE_LIST:
                            ProxyGetResponseList proxyGetResponseList = proxyResponse.getProxyGetResponseList();
                            // 创建SubSeqOfResult对象并填充数据
                            SubSeqOfResult subSeqOfResult = new SubSeqOfResult();
                            SubSeqOfProxyGetResponseResult proxyResults = proxyGetResponseList.getResult();
                            // 遍历proxyResults并填充subSeqOfResult
                            for (int i = 0; i < proxyResults.size(); i++) {
                                ProxyGetResponse proxyGetResponse = proxyResults.get(i);
                                SubSeqOfProxyGet proxyGets = proxyGetResponse.getResult();
                                // 将proxyGets中的每个ProxyGet添加到subSeqOfResult中
                                for (int j = 0; j < proxyGets.size(); j++) {
                                    ProxyGet proxyGet = proxyGets.get(j);
                                    subSeqOfResult.add(proxyGet);
                                }
                            }
                            result = ParseProxyResponse.parseProxyGetResponseList(subSeqOfResult);
                            break;
                        case PROXY_GET_RESPONSE_RECORD:
                            result = ParseProxyResponse.parseProxyGetRecord(proxyResponse.getProxyGetResponseRecord());
                            break;
                        case PROXY_SET_RESPONSE_LIST:
                            result = ParseProxyResponse
                                    .parseProxySetResponseNormalList(proxyResponse.getProxySetResponseList());
                            break;
                        case PROXY_SET_THEN_GET_RESPONSE_LIST:
                            result = ParseProxyResponse
                                    .parseProxySetThenGetResponseList(proxyResponse.getProxySetThenGetResponseList());
                            break;
                        case PROXY_ACTION_RESPONSE_LIST:
                            result = ParseProxyResponse
                                    .parseProxyActionResponseList(proxyResponse.getProxyActionResponseList());
                            break;
                        case PROXY_ACTION_THEN_GET_RESPONSE_LIST:
                            result = ParseProxyResponse.parseProxyActionThenGetResponseList(
                                    proxyResponse.getProxyActionThenGetResponseList());
                            break;
                        case PROXY_TRANS_COMMAND_RESPONSE:
                            result = ParseProxyResponse
                                    .parseProxyTransCommand(proxyResponse.getProxyTransCommandResponse());
                            break;
                    }
                    break;
            }
        } catch (Exception e) {
            return "Parse error: " + e.getMessage();
        }

        return result;
    }

    // 以下是私有辅助方法，处理不同类型的请求

    private FrameData handleGetRequest(RequestOption requestOption, LinkOption linkOpt) {
        // 实现GET请求处理逻辑
        FrameData result = new FrameData();
        result.setCode(ResultCode.SUCCESS);
        result.setData("GET request handled");
        return result;
    }

    private FrameData handleSetRequest(RequestOption requestOption, LinkOption linkOpt) {
        // 实现SET请求处理逻辑
        FrameData result = new FrameData();
        result.setCode(ResultCode.SUCCESS);
        result.setData("SET request handled");
        return result;
    }

    private FrameData handleActionRequest(RequestOption requestOption, LinkOption linkOpt) {
        // 实现ACTION请求处理逻辑
        FrameData result = new FrameData();
        result.setCode(ResultCode.SUCCESS);
        result.setData("ACTION request handled");
        return result;
    }

    private FrameData handleConnectRequest(RequestOption requestOption, LinkOption linkOpt) {
        // 实现CONNECT请求处理逻辑
        FrameData result = new FrameData();
        result.setCode(ResultCode.SUCCESS);
        result.setData("CONNECT request handled");
        return result;
    }

    private FrameData handleProxyRequest(RequestOption requestOption, LinkOption linkOpt) {
        // 实现PROXY请求处理逻辑
        FrameData result = new FrameData();
        result.setCode(ResultCode.SUCCESS);
        result.setData("PROXY request handled");
        return result;
    }

    private FrameData handleSecurityRequest(RequestOption requestOption, LinkOption linkOpt) {
        // 实现SECURITY请求处理逻辑
        FrameData result = new FrameData();
        result.setCode(ResultCode.SUCCESS);
        result.setData("SECURITY request handled");
        return result;
    }
}